import type { Directive } from 'vue';
import vtTouchCom from '../v-drag/vtTouchCom.ts';
const vTmp: any = {};
interface DragZoomBinding {
    ujt?: any;
    pos?: { x: number; y: number };
    dom?: string;
    domarea?: string;
    dommask?: string;
}

const vDragzoom: Directive = {
    mounted(el: HTMLElement, binding: { value: DragZoomBinding }) {
        const { fnPThrottle, vtTouchInit, vtTouchDown, vtTouchUp } = vtTouchCom(
            el,
            binding.value
        );
        vtTouchInit(el);
        let isDragging = false;
        let startPos = { x: 0, y: 0 };
        let newPos = { x: 0, y: 0 };
        let containerRect: any = null;
        let scale = 1;

        const dragDom: any =
            (binding.value?.dom
                ? document.getElementById(binding.value.dom)
                : '') || el;
        const dragAreaDom: any =
            (binding.value?.domarea
                ? document.getElementById(binding.value.domarea)
                : '') || dragDom;
        const dragMaskDom: any =
            (binding.value?.dommask
                ? document.getElementById(binding.value.dommask)
                : '') ||
            (binding.value?.ujt?.$global?.sys?.zoomid
                ? document.getElementById(binding.value.ujt.$global.sys.zoomid)
                : '') ||
            document.getElementById('asaizoomarea') ||
            document.body;

        const getScale = () => {
            if (!dragMaskDom) return 1;
            return binding.value?.ujt?.$global?.scale || 1;
        };

        const handleDown = (e: PointerEvent) => {
            if (!dragMaskDom) return;
            vtTouchDown(el);
            e.preventDefault(); // 阻止默认触摸行为

            scale = getScale();
            if (binding.value?.pos) {
                newPos = binding.value.pos;
            } else {
                const dragAreaStyle: any = window.getComputedStyle(dragAreaDom);
                const transformArr = dragAreaStyle.transform?.split(', ');
                if (transformArr.length > 2) {
                    const valy = transformArr.pop().slice(0, -1) || 0;
                    const valx = transformArr.pop() || 0;
                    newPos = {
                        x: parseFloat(valx),
                        y: parseFloat(valy),
                    };
                } else {
                    newPos = {
                        x: 0,
                        y: 0,
                    };
                }
            }
            isDragging = true;
            containerRect = dragMaskDom.getBoundingClientRect();

            let clientX: number, clientY: number;
            clientX = e.clientX;
            clientY = e.clientY;

            startPos = {
                x: (clientX - containerRect.left) / scale - newPos.x,
                y: (clientY - containerRect.top) / scale - newPos.y,
            };

            dragDom.setPointerCapture(e.pointerId);
            document.addEventListener('pointermove', handleMove);
            document.addEventListener('pointerup', handleUp);
            document.addEventListener('pointercancel', handleUp);
        };

        const handleMove = (e: PointerEvent) => {
            if (!isDragging || !containerRect) return;

            let clientX: number, clientY: number;
            clientX = e.clientX;
            clientY = e.clientY;
            scale = getScale();
            const realX = (clientX - containerRect.left) / scale - startPos.x;
            const realY = (clientY - containerRect.top) / scale - startPos.y;

            const maxX = dragMaskDom!.offsetWidth - dragAreaDom.offsetWidth;
            const maxY = dragMaskDom!.offsetHeight - dragAreaDom.offsetHeight;
            fnPThrottle(() => {
                if (binding.value.pos) {
                    binding.value.pos.x = +Math.max(
                        0,
                        Math.min(realX, maxX)
                    ).toFixed(6);
                    binding.value.pos.y = +Math.max(
                        0,
                        Math.min(realY, maxY)
                    ).toFixed(6);
                } else {
                    dragAreaDom.style.transform = `translate(${+Math.max(
                        0,
                        Math.min(realX, maxX)
                    ).toFixed(6)}px,${+Math.max(
                        0,
                        Math.min(realY, maxY)
                    ).toFixed(6)}px)`;
                }
            });
        };
        const handleUp = (e: PointerEvent) => {
            vtTouchUp(el);
            if (
                e instanceof PointerEvent &&
                dragDom.hasPointerCapture(e.pointerId)
            ) {
                isDragging = false;
                dragDom.releasePointerCapture(e.pointerId);
            }

            document.removeEventListener('pointermove', handleMove);
            document.removeEventListener('pointerup', handleUp);
            document.removeEventListener('pointercancel', handleUp);
        };

        dragDom.addEventListener('pointerdown', handleDown);

        const handleResize = () => (containerRect = null);
        window.addEventListener('resize', handleResize);

        vTmp.unmounted = () => {
            dragDom.removeEventListener('pointerdown', handleDown);
            window.removeEventListener('resize', handleResize);
        };
    },
    unmounted(el) {
        typeof vTmp?.unmounted == 'function' && vTmp.unmounted();
    },
};

export default vDragzoom;
